﻿using System;
using System.Net.Http;
using System.Threading.Tasks;
using Demo.Identity.Dto;
using IdentityModel.Client;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Volo.Abp.AspNetCore.Mvc;

namespace Demo.Identity.Controllers;

/// <summary>
/// 用户登录控制器
/// </summary>
[ApiController]
[Route("api/[controller]/[action]")]
public class AuthController : AbpController
{
    private readonly IConfiguration _configuration;

    public AuthController(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    /// <summary>
    /// 检查IdentityServer服务链接并获取相关接口地址
    /// </summary>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    private async Task<DiscoveryDocumentResponse> CheckIdsService()
    {
        var client = new HttpClient();
        var disco = await client.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest
            { Address = _configuration["AuthService"], Policy = { RequireHttps = false } });
        if (disco.IsError)
        {
            throw new LoginException("身份认证服务链接失败");
        }

        return disco;
    }

    /// <summary>
    /// 用户名密码登录
    /// </summary>
    /// <param name="request">请求实体</param>
    /// <returns>登录响应</returns>
    [HttpPost]
    [LoginExceptionFilter]
    public async Task<LoginResponse> Login([FromBody] PasswordLoginRequest request)
    {
        var disco = await CheckIdsService();
        var tokenResponse = await new HttpClient().RequestPasswordTokenAsync(new PasswordTokenRequest
        {
            Address = disco.TokenEndpoint,

            ClientId = "Demo_App",
            ClientSecret = "1q2w3e*",
            UserName = request.UserName,
            Password = request.Password,
            Scope = "openid offline_access"
        });
        if (tokenResponse.IsError)
        {
            throw new LoginException("用户名密码错误");
        }

        return new LoginResponse
        {
            AccessToken = tokenResponse.AccessToken,
            RefreshToken = tokenResponse.RefreshToken,
            ExpireInSeconds = tokenResponse.ExpiresIn
        };

    }

    /// <summary>
    /// 刷新Token
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPost]
    [LoginExceptionFilter]
    public async Task<LoginResponse> RefreshToken([FromBody] Dto.RefreshTokenRequest request)
    {
        var disco = await CheckIdsService();
        var tokenResponse = await new HttpClient().RequestRefreshTokenAsync(
            new IdentityModel.Client.RefreshTokenRequest()
            {
                Address = disco.TokenEndpoint,

                ClientId = "Demo_App",
                ClientSecret = "1q2w3e*",
                RefreshToken = request.RefreshToken,
                Scope = "openid offline_access"
            });
        if (tokenResponse.IsError)
        {
            throw new LoginException("RefreshToken已过期");
        }

        return new LoginResponse
        {
            AccessToken = tokenResponse.AccessToken,
            RefreshToken = tokenResponse.RefreshToken,
            ExpireInSeconds = tokenResponse.ExpiresIn
        };
    }
}